package com.neusoft.thread7callfuture;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * Callable和Future，它俩很有意思的，一个产生结果，一个拿到结果。 
 * Callable接口类似于Runnable，从名字就可以看出来了，但是Runnable不会返回结果，并且无法抛出返回结果的异常，
 * 而Callable功能更强大一些，被线程执行后，可以返回值，这个返回值可以被Future拿到，也就是说，Future可以拿到异步执行任务的返回值
 * @author Zhang.Yan
 *
 */
public class CallableAndFutureTest 
{
	public static void pureCallableAndFuture()
	{
		Callable<Integer> callable=new Callable<Integer>() {

			@Override
			public Integer call() throws Exception {
				System.out.println("call");
	            Thread.sleep(3000);// 可能做一些事情
				return new Random().nextInt(100);
			}
		};
		
		FutureTask<Integer> future=new FutureTask<Integer>(callable);
		new Thread(future).start();
		try 
		{
			System.out.println("main do something start");
            Thread.sleep(1000);// 可能做一些事情
            System.out.println(future.get());
            System.out.println("main do something end");
        } 
		catch (InterruptedException e) 
		{
            e.printStackTrace();
        } 
		catch (ExecutionException e) 
		{
			e.printStackTrace();
		}
	}
	
	
	public static void execCallableAndFuture()
	{
		ExecutorService execServ=Executors.newSingleThreadExecutor();
		final Future<Integer> future=execServ.submit(new Callable<Integer>() 
		{
			@Override
			public Integer call() throws Exception 
			{
				System.out.println("call");
	            Thread.sleep(3000);// 可能做一些事情
				return new Random().nextInt(100);
			}
		});
		
		new Thread(){
			public void run() {
				try 
				{
					System.out.println(future.get());
				} 
				catch (InterruptedException e) 
				{
					e.printStackTrace();
				} 
				catch (ExecutionException e) 
				{
					e.printStackTrace();
				}
			};
		}.start();
		execServ.shutdown();
	}
	
	public static void compCallableAndFuture()
	{
		ExecutorService execServ=Executors.newCachedThreadPool();
		CompletionService<Integer> cs=new ExecutorCompletionService<Integer>(execServ);
		for(int i=0;i<5;i++)
		{
			final int taskID=i;
			cs.submit(new Callable<Integer>() 
			{
				@Override
				public Integer call() throws Exception 
				{
					return taskID;
				}
			});
		}
		
		for(int i=0;i<5;i++)
		{
			try 
			{
				System.out.println(cs.take().get());
			}
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			} 
			catch (ExecutionException e) 
			{
				e.printStackTrace();
			}
		}
		execServ.shutdown();
	}

	public static void main(String[] args) 
	{

//		pureCallableAndFuture();
		execCallableAndFuture();
//		compCallableAndFuture();
	}

}
